/**************************************************************************
 * @file usr_pid.h
 * @author 黑马小乌龟 (532352406@qq.com)
 * @brief 
 * @version 0.1
 * @date 2025-08-13
 * 
 * @copyright Copyright (c) 2025
 * 
 *************************************************************************/
#ifndef USR_PID__H_H
#define USR_PID__H_H

#ifdef __cplusplus
extern "C"{
#endif
#include<stdint.h>
#include<stdio.h>

/********************************************************************************
增量式PI控制器是离散控制系统中常用的一种算法，其输出为控制量的增量而非绝对量。核心公式为
Δu(k) = Kp × [e(k) - e(k-1)] + Ki × Ts × e(k)
u(k) = u(k-1) + Δu(k)
    *Δu(k)：当前控制增量
    *u(k)：当前控制量
    *e(k)：当前误差（设定值 - 测量值）
    *Kp：比例增益
    *Ki：积分增益（Ki = Kp × Ts / Ti）
    *Ts：采样周期
    *Ti：积分时间常数
*********************************************************/

/****************************************************
参数整定指南
    参数	       整定方法	                典型值范围
    Kp	    从0开始增大至系统出现轻微振荡	   0.1~100.0
    Ti	    取系统响应时间的0.2~0.6倍	      温度: 30-600s
                                            电机: 0.01-1.0s
    Ts	    取系统响应时间的1/10~1/20	      1ms~1000ms
    inc_max	执行机构最大变化率的80%	          步进电机: 1-5步
******************************************************/

typedef struct {
    float Kp;           // 比例增益
    float Ki;           // 积分增益 (Ki = Kp * Ts / Ti)
    float out_min;      // 输出下限
    float out_max;      // 输出上限
    float inc_max;      // 最大增量限制
    float prev_error;   // 前次误差 e(k-1)
    float prev_output;  // 前次输出 u(k-1)
    float iv_sw_output; // 恒压/恒流切换时的PID输出绝对调整量
} usr_IncPID;


typedef struct {
    float Kp;           // 比例增益
    float Ki;           // 积分增益 (Ki = Kp * Ts / Ti)
    int32_t out_min;      // 输出下限
    int32_t out_max;      // 输出上限
    int32_t inc_max;      // 最大增量限制
    float prev_error;   // 前次误差 e(k-1)
    int32_t prev_output;  // 前次输出 u(k-1)
    int32_t iv_sw_output; // 恒压/恒流切换时的PID输出绝对调整量
} usr_int_pi;

float usr_PID_Compute(usr_IncPID *pid, float setpoint, float pv);
void usr_PID_Init(usr_IncPID *pid, float Kp, float Ki,/*float Ti, float Ts,*/ 
              float min, float max, float inc_max);
void usr_PID_Reset(usr_IncPID *pid, float init_output);


int32_t usr_pi_int_compute(usr_int_pi *p_pid, int32_t setpoint, int32_t pv);
void usr_pi_int_reset(usr_int_pi *pid, int32_t init_output);
void usr_pi_int_Init(usr_int_pi *pid, float Kp, float Ki, int32_t min, int32_t max, int32_t inc_max);


#ifdef __cplusplus
}
#endif

#endif //USR_PID__H_H


